package keeto.com.vn.classified.ui;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import keeto.com.vn.classified.config.ICompileTimestamp;
import keeto.com.vn.classified.config.ISVNRev;
import keeto.com.vn.classified.utils.Base64;
import keeto.com.vn.classified.utils.DeviceInfoUtil;
import keeto.com.vn.classified.utils.ImageUtilities;
import keeto.com.vn.classified.utils.OperationRecord;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.util.Log;

public class CustomExceptionHandler implements UncaughtExceptionHandler {

	private String localPath;

	private String url;

	private Context context;

	public static String user_id = "";
	public static Hashtable extra_Info = null;

	final String KEY_PACKAGE_VERSION = "package_version";
	final String KEY_PACKAGE_NAME = "package_name";

	/*
	 * if any of the parameters is null, the respective functionality will not
	 * be used
	 */
	public CustomExceptionHandler(String localPath, String url, Context cxt) {
		this.localPath = localPath;
		this.url = url;
		this.context = cxt;
		setExtraInfo(context);
	}

	@Override
	public void uncaughtException(Thread t, Throwable e) {

		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
		Date curDate = new Date(System.currentTimeMillis());//
		String timestamp = formatter.format(curDate);
		final Writer result = new StringWriter();
		final PrintWriter printWriter = new PrintWriter(result);
		e.printStackTrace(printWriter);
		String stacktrace = result.toString();
		printWriter.close();
		String filename = timestamp + ".stacktrace";
		e.printStackTrace();

		if (url != null) {

			LinkedList<String> records = OperationRecord.getRecord();
			StringBuilder sb = new StringBuilder();
			if (0 < records.size()) {
				sb.append(" < =Operation information= >").append("\r\n");
				for (String s : records) {
					sb.append(s).append("\r\n");
				}
			}
			sendToServer(stacktrace + sb.toString());
			OperationRecord.removeTrack();
		}

		checkLocalPath();
		if (localPath != null) {
			writeToFile(extra_Info + "\n" + stacktrace, filename);
		}
		e.printStackTrace();
	}

	public static boolean isSdPresent() {
		return android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED);
	}

	private void checkLocalPath() {
		if (isSdPresent()) {
			File dir = new File(Environment.getExternalStorageDirectory()
					+ localPath);
			if (dir.exists() && dir.isDirectory()) {
				localPath = Environment.getExternalStorageDirectory()
						+ localPath;
			} else {
				localPath = Environment.getExternalStorageDirectory()
						+ localPath;
				dir.mkdirs();
			}
		} else {
			localPath = null;
		}
	}

	private void writeToFile(String stacktrace, String filename) {
		try {
			BufferedWriter bos = new BufferedWriter(new FileWriter(localPath
					+ "/" + filename));
			bos.write(stacktrace);
			bos.flush();
			bos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * $user_id = $_POST("user_id"); $version = $_POST['package_version'];
	 * $package = $_POST['package_name']; $stacktrace = $_POST['stacktrace'];
	 * $extra_info = $_POST['extra_info'];
	 */
	private void sendToServer(String stacktrace) {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(url);
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		try {

			String package_version = "";
			String package_name = "";
			PackageInfo pinfo = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			package_version = pinfo.versionName;
			package_name = pinfo.packageName;

			nvps.add(new BasicNameValuePair("user_id", user_id));
			nvps.add(new BasicNameValuePair("package_version", package_version));
			nvps.add(new BasicNameValuePair("package_name", package_name));
			nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
			nvps.add(new BasicNameValuePair("compile_on",
					ICompileTimestamp.COMPILE_TIME));
			nvps.add(new BasicNameValuePair("svn_rev", ISVNRev.SVN_REV));

			Enumeration<String> keys = extra_Info.keys();
			JSONObject jo = new JSONObject();
			while (keys.hasMoreElements()) {
				String key = keys.nextElement();
				String value = extra_Info.get(key) + "";
				jo.put(key, value);
			}

			if (stacktrace.contains("OutOfMemory")) {
				jo.put("bitmapFilePath", ImageUtilities.FILE_ABOUT_TO_DECODE);

				File file = new File(ImageUtilities.FILE_ABOUT_TO_DECODE);
				if (file.exists()) {
					FileInputStream fos = new FileInputStream(file);
					byte[] data = new byte[50 * 1024];
					fos.read(data);
					jo.put("BitmapfileSize", file.length());
					jo.put("Bitmapfile50K", Base64.encodeToString(data, false));
				}
			}

			String extraInfo = jo.toString();
			nvps.add(new BasicNameValuePair("extra_info", extraInfo));
			Log.i("ExceptionHandler", "***sendToServer");
			httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
			httpClient.execute(httpPost);

		} catch (IOException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void setUser_id(String _user_id) {
		user_id = _user_id;
	}

	public static void setExtraInfo(Context context) {
		extra_Info = DeviceInfoUtil.getDeviceInfo(context);
	}

}
